﻿/* Copyright (C) 2007-2010 STS Soft

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace STSdb.General.Reflection
{
    public class FactoryReflector<T>
    {
#if !WindowsCE && !PocketPC
        public static readonly Type[] EmptyTypes = Type.EmptyTypes;
#else
        public static readonly Type[] EmptyTypes = new Type[0];
#endif

        private Func<T> createInstanceDelegate;

        public FactoryReflector()
        {
            Type type = typeof(T);

            Expression body;
            if (type.GetConstructor(EmptyTypes) == null)
            {
                if (type.IsValueType)
                    body = Expression.Constant(default(T));
                else
                    body = Expression.Convert(Expression.Constant(null), type);
            }
            else
                body = Expression.New(type);

            var lambda = Expression.Lambda<Func<T>>(body);
            createInstanceDelegate = (Func<T>)lambda.Compile();
        }

        public T CreateInstance()
        {
            return createInstanceDelegate();
        }
    }

    //TODO: remove in C# 4
    public class FactoryReflector
    {
#if !WindowsCE && !PocketPC
        public static readonly Type[] EmptyTypes = Type.EmptyTypes;
#else
        public static readonly Type[] EmptyTypes = new Type[0];
#endif

        private Func<object> createInstanceDelegate;

        public FactoryReflector(Type type)
        {
            if (null == type)
                throw new ArgumentNullException("type");

            if (type.GetConstructor(EmptyTypes) != null)
            {
                var lambda = Expression.Lambda<Func<object>>(Expression.Constant(null));

                createInstanceDelegate = (Func<object>)lambda.Compile();
            }
            else
            {
                var obj = Expression.New(type);
                var lambda = Expression.Lambda<Func<object>>(obj);

                createInstanceDelegate = lambda.Compile();
            }
        }

        public object CreateInstance()
        {
            return createInstanceDelegate();
        }
    }
}
